package com.harmony.pilot.data.service;

import com.harmony.pilot.common.dto.ASTSymbol;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.io.BufferedReader;
import java.io.File;
import java.io.InputStreamReader;
import java.nio.file.Files;
import java.util.*;
import java.util.stream.Collectors;

/**
 * OpenHarmony组件服务
 * 识别和查询OpenHarmony组件（如包管理、Samgr等）的能力和API
 */
@Service
@Slf4j
public class OpenHarmonyComponentService {
    
    @Value("${codeql.database-path}")
    private String databasePath;
    
    @Value("${codeql.cli-path:codeql}")
    private String cliPath;
    
    // OpenHarmony组件映射（组件名称 -> 关键词和路径模式）
    private static final Map<String, ComponentInfo> COMPONENT_MAP = new HashMap<>();
    
    static {
        // 包管理（Bundle Manager）
        COMPONENT_MAP.put("包管理", new ComponentInfo(
            Arrays.asList("bundle", "包管理", "bundle manager", "bundlemanager"),
            Arrays.asList("bundlemgr", "bundle_manager", "bundlemanager"),
            Arrays.asList("BundleInfo", "BundleInstaller", "BundleMgrClient", "IBundleMgr"),
            "OpenHarmony包管理系统，提供应用安装、卸载、查询等功能"
        ));
        
        // Samgr（System Ability Manager）
        COMPONENT_MAP.put("Samgr", new ComponentInfo(
            Arrays.asList("samgr", "system ability", "系统能力", "sa"),
            Arrays.asList("samgr", "systemability", "sa_mgr"),
            Arrays.asList("SystemAbilityManager", "SaManager", "ISystemAbilityManager"),
            "OpenHarmony系统能力管理器，提供分布式能力注册、发现、调用等功能"
        ));
        
        // 分布式数据管理
        COMPONENT_MAP.put("分布式数据", new ComponentInfo(
            Arrays.asList("分布式数据", "distributed data", "distributeddata", "kvstore"),
            Arrays.asList("distributeddata", "kv_store", "distributeddatamgr"),
            Arrays.asList("DistributedKvDataManager", "KvStore", "SingleKvStore"),
            "OpenHarmony分布式数据管理，提供跨设备数据同步能力"
        ));
        
        // 分布式硬件
        COMPONENT_MAP.put("分布式硬件", new ComponentInfo(
            Arrays.asList("分布式硬件", "distributed hardware", "distributedhardware"),
            Arrays.asList("distributedhardware", "distributed_hardware"),
            Arrays.asList("DistributedHardwareManager", "IDistributedHardwareManager"),
            "OpenHarmony分布式硬件管理，提供跨设备硬件资源访问能力"
        ));
        
        // 文件管理
        COMPONENT_MAP.put("文件管理", new ComponentInfo(
            Arrays.asList("文件管理", "file management", "filemanagement"),
            Arrays.asList("filemanagement", "file_management"),
            Arrays.asList("FileManager", "IFileManager", "FileAccessHelper"),
            "OpenHarmony文件管理系统，提供文件访问、存储管理等功能"
        ));
        
        // 通知管理
        COMPONENT_MAP.put("通知", new ComponentInfo(
            Arrays.asList("通知", "notification", "notification"),
            Arrays.asList("notification", "notification_service"),
            Arrays.asList("NotificationHelper", "INotificationManager"),
            "OpenHarmony通知管理系统，提供系统通知、订阅等功能"
        ));
    }
    
    public OpenHarmonyComponentService() {
    }
    
    /**
     * 识别用户提到的OpenHarmony组件
     * 
     * @param userMessage 用户消息
     * @return 识别的组件列表
     */
    public List<ComponentMatch> identifyComponents(String userMessage) {
        List<ComponentMatch> matches = new ArrayList<>();
        
        if (userMessage == null || userMessage.isEmpty()) {
            return matches;
        }
        
        String lowerMessage = userMessage.toLowerCase();
        
        // 遍历所有组件，查找匹配
        for (Map.Entry<String, ComponentInfo> entry : COMPONENT_MAP.entrySet()) {
            String componentName = entry.getKey();
            ComponentInfo info = entry.getValue();
            
            // 检查关键词匹配
            double score = 0.0;
            for (String keyword : info.getKeywords()) {
                if (lowerMessage.contains(keyword.toLowerCase())) {
                    score += 0.3;
                }
            }
            
            // 精确匹配组件名称
            if (lowerMessage.contains(componentName.toLowerCase())) {
                score += 0.5;
            }
            
            if (score > 0.1) {
                matches.add(new ComponentMatch(componentName, info, score));
            }
        }
        
        // 按分数排序
        matches.sort((a, b) -> Double.compare(b.getScore(), a.getScore()));
        
        log.info("Identified {} components from message: {}", matches.size(), userMessage);
        return matches;
    }
    
    /**
     * 查询组件的API列表
     * 
     * @param componentName 组件名称
     * @param capability 具体能力描述（可选）
     * @return API列表
     */
    @Cacheable(value = "oh-component-apis", key = "#componentName + ':' + (#capability != null ? #capability : '')")
    public List<ComponentAPI> queryComponentAPIs(String componentName, String capability) {
        log.info("Querying APIs for component: {} (capability: {})", componentName, capability);
        
        ComponentInfo componentInfo = COMPONENT_MAP.get(componentName);
        if (componentInfo == null) {
            log.warn("Unknown component: {}", componentName);
            return new ArrayList<>();
        }
        
        List<ComponentAPI> apis = new ArrayList<>();
        
        try {
            // 1. 使用CodeQL查询组件相关的类和函数
            List<ASTSymbol> symbols = queryComponentSymbols(componentInfo, capability);
            
            // 2. 转换为API对象
            for (ASTSymbol symbol : symbols) {
                ComponentAPI api = convertToAPI(symbol, componentInfo);
                if (api != null) {
                    apis.add(api);
                }
            }
            
            // 3. 如果CodeQL查询结果不足，使用预定义的API
            if (apis.isEmpty()) {
                apis.addAll(getPredefinedAPIs(componentInfo));
            }
            
            // 4. 根据能力描述过滤
            if (capability != null && !capability.isEmpty()) {
                apis = filterAPIsByCapability(apis, capability);
            }
            
            log.info("Found {} APIs for component {}", apis.size(), componentName);
            
        } catch (Exception e) {
            log.error("Failed to query component APIs", e);
            // 返回预定义API作为fallback
            apis.addAll(getPredefinedAPIs(componentInfo));
        }
        
        return apis;
    }
    
    /**
     * 使用CodeQL查询组件符号
     */
    private List<ASTSymbol> queryComponentSymbols(ComponentInfo componentInfo, String capability) {
        try {
            // 构建CodeQL查询
            String query = buildComponentQuery(componentInfo, capability);
            
            // 执行查询
            File queryFile = File.createTempFile("codeql-component-", ".ql");
            queryFile.deleteOnExit();
            Files.writeString(queryFile.toPath(), query);
            
            ProcessBuilder pb = new ProcessBuilder(
                cliPath,
                "query", "run",
                "--database=" + databasePath,
                "--format=csv",
                queryFile.getAbsolutePath()
            );
            
            Process process = pb.start();
            
            List<ASTSymbol> symbols = new ArrayList<>();
            try (BufferedReader reader = new BufferedReader(
                    new InputStreamReader(process.getInputStream()))) {
                String line;
                while ((line = reader.readLine()) != null) {
                    if (line.trim().isEmpty() || line.startsWith("#")) {
                        continue;
                    }
                    ASTSymbol symbol = parseSymbolFromLine(line);
                    if (symbol != null) {
                        symbols.add(symbol);
                    }
                }
            }
            
            process.waitFor();
            return symbols;
            
        } catch (Exception e) {
            log.error("Failed to query component symbols from CodeQL", e);
            return new ArrayList<>();
        }
    }
    
    /**
     * 构建CodeQL查询
     */
    private String buildComponentQuery(ComponentInfo componentInfo, String capability) {
        StringBuilder query = new StringBuilder();
        query.append("import cpp\n\n");
        query.append("from Class c, Function f\n");
        query.append("where ");
        
        // 匹配类名或命名空间
        query.append("(");
        boolean first = true;
        for (String className : componentInfo.getClassNames()) {
            if (!first) query.append(" or ");
            query.append("c.getName().matches(\"%").append(className).append("%\")");
            first = false;
        }
        query.append(")\n");
        
        query.append("  and f.getEnclosingClass() = c\n");
        query.append("select ");
        query.append("f.getName() as name, ");
        query.append("\"Function\" as type, ");
        query.append("f.getQualifiedName() as qualifiedName, ");
        query.append("f.getType() as returnType, ");
        query.append("f.getParameters() as parameters, ");
        query.append("f.getLocation().getStartLine() as startLine, ");
        query.append("f.getFile().getRelativePath() as filePath\n");
        query.append("limit 50");
        
        return query.toString();
    }
    
    /**
     * 从行解析符号
     */
    private ASTSymbol parseSymbolFromLine(String line) {
        try {
            String[] parts = line.split("\\|");
            if (parts.length >= 3) {
                ASTSymbol symbol = new ASTSymbol();
                symbol.setName(parts[0].trim());
                symbol.setType(parts[1].trim());
                symbol.setQualifiedName(parts[2].trim());
                if (parts.length > 3) {
                    symbol.setReturnType(parts[3].trim());
                }
                if (parts.length > 4) {
                    symbol.setParameters(parts[4].trim());
                }
                if (parts.length > 6) {
                    try {
                        symbol.setStartLine(Integer.parseInt(parts[5].trim()));
                    } catch (NumberFormatException e) {
                        // 忽略
                    }
                    symbol.setFilePath(parts[6].trim());
                }
                return symbol;
            }
        } catch (Exception e) {
            log.debug("Failed to parse symbol from line: {}", line, e);
        }
        return null;
    }
    
    /**
     * 转换为API对象
     */
    private ComponentAPI convertToAPI(ASTSymbol symbol, ComponentInfo componentInfo) {
        ComponentAPI api = new ComponentAPI();
        api.setName(symbol.getName());
        api.setQualifiedName(symbol.getQualifiedName());
        api.setReturnType(symbol.getReturnType());
        api.setParameters(symbol.getParameters());
        api.setFilePath(symbol.getFilePath());
        api.setLineNumber(symbol.getStartLine());
        
        // 提取模块路径和GN依赖
        if (symbol.getFilePath() != null) {
            String modulePath = extractModulePath(symbol.getFilePath());
            api.setModulePath(modulePath);
            api.setGnDepPath(inferGnDepFromModule(modulePath));
            api.setCrossModule(true); // 如果是从CodeQL查询的，通常是跨模块的
        }
        
        // 提取需要的头文件
        api.setRequiredHeaders(extractRequiredHeaders(symbol));
        
        // 生成描述
        api.setDescription(generateAPIDescription(symbol, componentInfo));
        
        // 生成使用示例
        api.setExample(generateUsageExample(symbol, componentInfo));
        
        return api;
    }
    
    /**
     * 从文件路径提取模块路径
     */
    private String extractModulePath(String filePath) {
        if (filePath == null || filePath.isEmpty()) {
            return null;
        }
        
        // 移除文件名，保留目录路径
        int lastSlash = filePath.lastIndexOf('/');
        if (lastSlash > 0) {
            return filePath.substring(0, lastSlash);
        }
        
        return null;
    }
    
    /**
     * 提取需要的头文件
     */
    private List<String> extractRequiredHeaders(ASTSymbol symbol) {
        List<String> headers = new ArrayList<>();
        
        if (symbol.getFilePath() != null) {
            // 从文件路径推断头文件路径
            String filePath = symbol.getFilePath();
            if (filePath.endsWith(".cpp") || filePath.endsWith(".cc")) {
                // 对应的头文件
                String headerPath = filePath.replaceAll("\\.(cpp|cc)$", ".h");
                headers.add(headerPath);
            }
            
            // 如果函数在类中，添加类对应的头文件
            if (symbol.getQualifiedName() != null && symbol.getQualifiedName().contains("::")) {
                String[] parts = symbol.getQualifiedName().split("::");
                if (parts.length > 1) {
                    String className = parts[parts.length - 2];
                    String modulePath = extractModulePath(filePath);
                    if (modulePath != null) {
                        headers.add(modulePath + "/" + className + ".h");
                    }
                }
            }
        }
        
        return headers;
    }
    
    /**
     * 获取预定义的API
     */
    private List<ComponentAPI> getPredefinedAPIs(ComponentInfo componentInfo) {
        List<ComponentAPI> apis = new ArrayList<>();
        
        // 根据组件类型返回预定义的API
        // 这里可以根据实际OpenHarmony代码库补充
        for (String className : componentInfo.getClassNames()) {
            ComponentAPI api = new ComponentAPI();
            api.setName(className);
            api.setQualifiedName("OHOS::" + className);
            api.setDescription("OpenHarmony " + componentInfo.getDescription());
            api.setExample(generatePredefinedExample(className, componentInfo));
            apis.add(api);
        }
        
        return apis;
    }
    
    /**
     * 根据能力过滤API
     */
    private List<ComponentAPI> filterAPIsByCapability(List<ComponentAPI> apis, String capability) {
        String lowerCapability = capability.toLowerCase();
        return apis.stream()
            .filter(api -> {
                String name = api.getName() != null ? api.getName().toLowerCase() : "";
                String desc = api.getDescription() != null ? api.getDescription().toLowerCase() : "";
                return name.contains(lowerCapability) || desc.contains(lowerCapability);
            })
            .collect(Collectors.toList());
    }
    
    /**
     * 生成API描述
     */
    private String generateAPIDescription(ASTSymbol symbol, ComponentInfo componentInfo) {
        StringBuilder desc = new StringBuilder();
        desc.append(componentInfo.getDescription());
        desc.append("。提供");
        desc.append(symbol.getName());
        desc.append("功能。");
        return desc.toString();
    }
    
    /**
     * 生成使用示例
     */
    private String generateUsageExample(ASTSymbol symbol, ComponentInfo componentInfo) {
        StringBuilder example = new StringBuilder();
        example.append("// 使用").append(symbol.getName()).append("\n");
        example.append("#include \"").append(componentInfo.getClassNames().get(0)).append(".h\"\n\n");
        example.append("// 创建实例\n");
        example.append("auto instance = ");
        
        if (symbol.getQualifiedName() != null && symbol.getQualifiedName().contains("::")) {
            String[] parts = symbol.getQualifiedName().split("::");
            example.append(parts[parts.length - 2]).append("::");
        }
        example.append("Create").append(componentInfo.getClassNames().get(0)).append("();\n");
        example.append("\n// 调用方法\n");
        example.append("// TODO: 添加参数\n");
        
        return example.toString();
    }
    
    /**
     * 生成预定义示例
     */
    private String generatePredefinedExample(String className, ComponentInfo componentInfo) {
        StringBuilder example = new StringBuilder();
        example.append("// ").append(componentInfo.getDescription()).append("\n");
        example.append("#include \"").append(className).append(".h\"\n\n");
        example.append("// 创建").append(className).append("实例\n");
        example.append("auto ").append(className.toLowerCase()).append(" = ");
        example.append("OHOS::").append(className).append("::GetInstance();\n");
        
        return example.toString();
    }
    
    /**
     * 组件信息
     */
    public static class ComponentInfo {
        private final List<String> keywords;
        private final List<String> pathPatterns;
        private final List<String> classNames;
        private final String description;
        
        public ComponentInfo(List<String> keywords, List<String> pathPatterns, 
                             List<String> classNames, String description) {
            this.keywords = keywords;
            this.pathPatterns = pathPatterns;
            this.classNames = classNames;
            this.description = description;
        }
        
        public List<String> getKeywords() { return keywords; }
        public List<String> getPathPatterns() { return pathPatterns; }
        public List<String> getClassNames() { return classNames; }
        public String getDescription() { return description; }
    }
    
    /**
     * 组件匹配结果
     */
    public static class ComponentMatch {
        private final String componentName;
        private final ComponentInfo componentInfo;
        private final double score;
        
        public ComponentMatch(String componentName, ComponentInfo componentInfo, double score) {
            this.componentName = componentName;
            this.componentInfo = componentInfo;
            this.score = score;
        }
        
        public String getComponentName() { return componentName; }
        public ComponentInfo getComponentInfo() { return componentInfo; }
        public double getScore() { return score; }
    }
    
    /**
     * 组件API信息
     */
    public static class ComponentAPI {
        private String name;
        private String qualifiedName;
        private String returnType;
        private String parameters;
        private String description;
        private String example;
        private String filePath;
        private int lineNumber;
        
        // 跨模块调用信息
        private String modulePath;           // 模块路径，如 foundation/arkui/napi
        private String gnDepPath;            // GN依赖路径，如 //foundation/arkui/napi:napi
        private List<String> requiredHeaders; // 需要的头文件
        private boolean isCrossModule;        // 是否跨模块调用
        
        // Getters and Setters
        public String getName() { return name; }
        public void setName(String name) { this.name = name; }
        
        public String getQualifiedName() { return qualifiedName; }
        public void setQualifiedName(String qualifiedName) { this.qualifiedName = qualifiedName; }
        
        public String getReturnType() { return returnType; }
        public void setReturnType(String returnType) { this.returnType = returnType; }
        
        public String getParameters() { return parameters; }
        public void setParameters(String parameters) { this.parameters = parameters; }
        
        public String getDescription() { return description; }
        public void setDescription(String description) { this.description = description; }
        
        public String getExample() { return example; }
        public void setExample(String example) { this.example = example; }
        
        public String getFilePath() { return filePath; }
        public void setFilePath(String filePath) { this.filePath = filePath; }
        
        public int getLineNumber() { return lineNumber; }
        public void setLineNumber(int lineNumber) { this.lineNumber = lineNumber; }
        
        public String getModulePath() { return modulePath; }
        public void setModulePath(String modulePath) { this.modulePath = modulePath; }
        
        public String getGnDepPath() { return gnDepPath; }
        public void setGnDepPath(String gnDepPath) { this.gnDepPath = gnDepPath; }
        
        public List<String> getRequiredHeaders() { return requiredHeaders; }
        public void setRequiredHeaders(List<String> requiredHeaders) { this.requiredHeaders = requiredHeaders; }
        
        public boolean isCrossModule() { return isCrossModule; }
        public void setCrossModule(boolean crossModule) { isCrossModule = crossModule; }
    }
    
    /**
     * 分析跨模块调用关系
     */
    public List<CrossModuleCall> analyzeCrossModuleCalls(String filePath, String functionName) {
        log.info("Analyzing cross-module calls for: {} in {}", functionName, filePath);
        
        List<CrossModuleCall> calls = new ArrayList<>();
        
        try {
            // 构建CodeQL查询跨模块调用
            String query = buildCrossModuleQuery(filePath, functionName);
            String result = executeCodeQLQuery(query);
            
            // 解析结果
            calls = parseCrossModuleCalls(result);
            
        } catch (Exception e) {
            log.error("Failed to analyze cross-module calls", e);
        }
        
        return calls;
    }
    
    /**
     * 构建跨模块调用查询
     */
    private String buildCrossModuleQuery(String filePath, String functionName) {
        StringBuilder query = new StringBuilder();
        query.append("import cpp\n\n");
        query.append("from FunctionCall call, Function caller, Function callee,\n");
        query.append("     File callerFile, File calleeFile\n");
        query.append("where ");
        query.append("call.getTarget() = callee\n");
        query.append("  and call.getEnclosingFunction() = caller\n");
        query.append("  and caller.getFile() = callerFile\n");
        query.append("  and callee.getFile() = calleeFile\n");
        
        if (filePath != null && !filePath.isEmpty()) {
            query.append("  and callerFile.getRelativePath().matches(\"%").append(escapeQueryString(filePath)).append("%\")\n");
        }
        
        if (functionName != null && !functionName.isEmpty()) {
            query.append("  and caller.getName().matches(\"%").append(escapeQueryString(functionName)).append("%\")\n");
        }
        
        query.append("  and regexpCapture(callerFile.getRelativePath(), \"^(.*?)/[^/]+$\", 1) != \n");
        query.append("      regexpCapture(calleeFile.getRelativePath(), \"^(.*?)/[^/]+$\", 1)\n");
        query.append("select ");
        query.append("callerFile.getRelativePath() as callerFile,\n");
        query.append("regexpCapture(callerFile.getRelativePath(), \"^(.*?)/[^/]+$\", 1) as callerModule,\n");
        query.append("calleeFile.getRelativePath() as calleeFile,\n");
        query.append("regexpCapture(calleeFile.getRelativePath(), \"^(.*?)/[^/]+$\", 1) as calleeModule,\n");
        query.append("callee.getName() as calleeFunction,\n");
        query.append("callee.getQualifiedName() as calleeQualifiedName\n");
        query.append("limit 50");
        
        return query.toString();
    }
    
    /**
     * 解析跨模块调用结果
     */
    private List<CrossModuleCall> parseCrossModuleCalls(String csvResult) {
        List<CrossModuleCall> calls = new ArrayList<>();
        
        String[] lines = csvResult.split("\n");
        for (String line : lines) {
            if (line.trim().isEmpty() || line.startsWith("#")) {
                continue;
            }
            
            String[] parts = line.split("\\|");
            if (parts.length >= 6) {
                CrossModuleCall call = new CrossModuleCall();
                call.setCallerFile(parts[0].trim());
                call.setCallerModule(parts[1].trim());
                call.setCalleeFile(parts[2].trim());
                call.setCalleeModule(parts[3].trim());
                call.setCalleeFunction(parts[4].trim());
                call.setCalleeQualifiedName(parts.length > 5 ? parts[5].trim() : "");
                
                // 推断GN依赖路径
                call.setGnDepPath(inferGnDepFromModule(call.getCalleeModule()));
                
                calls.add(call);
            }
        }
        
        return calls;
    }
    
    /**
     * 从模块路径推断GN依赖
     */
    private String inferGnDepFromModule(String modulePath) {
        if (modulePath == null || modulePath.isEmpty()) {
            return null;
        }
        
        // 提取模块的最后一段作为target名称
        String[] parts = modulePath.split("/");
        if (parts.length > 0) {
            String targetName = parts[parts.length - 1];
            return "//" + modulePath + ":" + targetName;
        }
        
        return null;
    }
    
    /**
     * 执行CodeQL查询
     */
    private String executeCodeQLQuery(String query) throws Exception {
        File queryFile = File.createTempFile("codeql-cross-module-", ".ql");
        queryFile.deleteOnExit();
        Files.writeString(queryFile.toPath(), query);
        
        ProcessBuilder pb = new ProcessBuilder(
            cliPath,
            "query", "run",
            "--database=" + databasePath,
            "--format=csv",
            queryFile.getAbsolutePath()
        );
        
        Process process = pb.start();
        
        StringBuilder output = new StringBuilder();
        try (BufferedReader reader = new BufferedReader(
                new InputStreamReader(process.getInputStream()))) {
            String line;
            while ((line = reader.readLine()) != null) {
                output.append(line).append("\n");
            }
        }
        
        process.waitFor();
        
        if (process.exitValue() != 0) {
            throw new Exception("CodeQL query failed with exit code: " + process.exitValue());
        }
        
        return output.toString();
    }
    
    /**
     * 转义查询字符串
     */
    private String escapeQueryString(String value) {
        if (value == null) {
            return "";
        }
        return value.replace("\"", "\\\"").replace("\\", "\\\\");
    }
    
    /**
     * 跨模块调用信息
     */
    public static class CrossModuleCall {
        private String callerFile;
        private String callerModule;
        private String calleeFile;
        private String calleeModule;
        private String calleeFunction;
        private String calleeQualifiedName;
        private String gnDepPath;
        
        // Getters and Setters
        public String getCallerFile() { return callerFile; }
        public void setCallerFile(String callerFile) { this.callerFile = callerFile; }
        
        public String getCallerModule() { return callerModule; }
        public void setCallerModule(String callerModule) { this.callerModule = callerModule; }
        
        public String getCalleeFile() { return calleeFile; }
        public void setCalleeFile(String calleeFile) { this.calleeFile = calleeFile; }
        
        public String getCalleeModule() { return calleeModule; }
        public void setCalleeModule(String calleeModule) { this.calleeModule = calleeModule; }
        
        public String getCalleeFunction() { return calleeFunction; }
        public void setCalleeFunction(String calleeFunction) { this.calleeFunction = calleeFunction; }
        
        public String getCalleeQualifiedName() { return calleeQualifiedName; }
        public void setCalleeQualifiedName(String calleeQualifiedName) { this.calleeQualifiedName = calleeQualifiedName; }
        
        public String getGnDepPath() { return gnDepPath; }
        public void setGnDepPath(String gnDepPath) { this.gnDepPath = gnDepPath; }
    }
}

